package tools

// 借鉴：https://mojotv.cn/go/golang-most-efficient-string-join

import (
	"bytes"
	"strings"
)

// 缺点：string是最基础的类型, 是一个只读类型,针对他的每一个操作都会创建一个新的string

// StringRepeat 合并大量重复的字符串(strings.Repeat)将count个字符串s连接成一个新的字符串
// strings.Repeat它的底层调用的是strings.Builder,提前分配了内存.
// conclusion: ① 使用strings.Repeat效率最高,从strings.Repeat源码它是提前分配内存,本质是使用pre allocate + strings.Builder.所以他的效率更高 18379 ns/op,大约是其他的1/10.
func StringRepeat(s string, count int) string {
	return strings.Repeat(s, count)
}

/*
StringBuilder 从Go 1.10(2018)版本开始可以使用 strings.Builder
	1. NOTICE: strings.Builder 使用 Write 方法来高效的构造字符串. 它使用内存最小,它使用零值,
它不拷贝零值. 注意:不要拷贝strings.Builder的值,如果您要使用strings.Builder值
请使用pointer 使用方法
	2. slice使用(four part)：
		2.1 初始化方法：
		var s1 []int         // len(s1)=0;cap(s1)=0;s1==nil
		s2 := []int{}        // len(s2)=0;cap(s2)=0;s2!=nil
		s3 := make([]int, 0) // len(s3)=0;cap(s3)=0;s3!=nil
		2.2 append()方法为切片添加元素
		s := []string{} // 没有必要初始化
		s = append(s, "啊", "是", "是")
		2.3 使用copy()函数复制切片：`copy(destSlice, srcSlice []T)`
		2.4 从切片中删除元素：`a = append(a[:2], a[3:]...)`// 要删除索引为2的元素
*/
func StringBuilder(s []string) string {
	if len(s) == 0 {
		return ""
	}
	var str strings.Builder
	for _, v := range s {
		// str.Write(v)
		str.WriteString(v)
	}
	return str.String()
}

/*
StringBuffer 在201X年之前使用bytes包的Buffer它实现了io.Writer的接口,
使用他来拼接字符串.他的事件复杂度O(n)
*/
// conclusion: string buffer write string 其次使用strings.Buffer 提前分配内存 120803 ns/op
// conclusion: Buffer Write bytes 和 Buffer Write string 几乎没有差别,因为在Go语言中 string 就是 []byte.
func StringBuffer(s []string) string {
	if len(s) == 0 {
		return ""
	}
	var buffer bytes.Buffer
	for _, v := range s {
		// buffer.Write(v)// Buffer Write bytes
		buffer.WriteString(v) // Buffer Write string
	}
	return buffer.String()
}

// conclusion: ④ 使用 + 连接字符串效率最低 87599885 ns/op
/*
StringCopy Go内建函数copy:func copy(dst, src []Type) int, 用于将源
slice的数据（第二个参数）,复制到目标slice（第一个参数）. 返回值为拷贝了的
数据个数,是len(dst)和len(src)中的最小值.
或者append
*/
// 缺点：需要指定目标切片destSlice的长度，少了合并出来的字符串会缺失
// func StringCopy(s []string) string {
// 	// 原因：一个汉字3个字节
// 	destSlice := make([]byte, len(s)*3)
// 	count := 0
// 	for _, v := range s {
// 		// copy把每一个切片单元加到切片末尾
// 		count += copy(destSlice[count:], v)
// 	}
// 	return string(destSlice)
// }
